package common

import (
	"context"
	"encoding/json"
	"net/http"
	"strings"
	"time"

	"github.com/gorhill/cronexpr"
)

// Job 定时任务
type Job struct {
	Name     string `json:"name"`
	Command  string `json:"command"`
	CronExpr string `json:"cronExpr"`
}

//变化事件
type JobEvent struct {
	EventType int // SAVE DELETE
	Job       *Job
}

//任务调度计划
type JobSchedulePlan struct {
	Job      *Job                 //任务信息
	Expr     *cronexpr.Expression // cron解析好的表达式
	NextTime time.Time            // 下次调度计划
}

//任务执行状态
type JobExecuteInfo struct {
	Job        *Job            //任务信息
	PlanTime   time.Time       // 理论上的调度时间
	RealTime   time.Time       // 实际调度时间
	CancelCtx  context.Context //用于取消任务的context
	CancelFunc context.CancelFunc
}

//任务执行结果
type JobExecuteResult struct {
	ExecuteInfo *JobExecuteInfo //执行状态
	Output      []byte          //脚本输出
	Err         error           // 脚本错误
	StartTime   time.Time       //启动时间
	EndTime     time.Time       //结束时间
}

//任务执行日志
type JobLog struct {
	JobName   string `json:"jobName" bson:"jobName"`     //任务名称
	Command   string `json:"command" bson:"command"`     //脚本命令
	Output    string `json:"output" bson:"output"`       //脚本输出
	Err       string `json:"err" bson:"err"`             // 脚本错误
	PlanTime  int64  `json:"planTime" bson:"planTime"`   // 理论上的调度时间
	RealTime  int64  `json:"realTime" bson:"realTime"`   // 实际调度时间
	StartTime int64  `json:"startTime" bson:"startTime"` //启动时间
	EndTime   int64  `json:"endTime" bson:"endTime"`     //结束时间
}

//日志批次
type LogBatch struct {
	Logs []interface{} //多条日志
}

type LogFiller struct {
	JobName string `bson:"jobName"` //任务名称
}

type SortLogByStartTime struct {
	SortOrder int `bson:"sortOrder"` //按startTime -1排序
}

type Response struct {
	Err  int         `json:"err"`
	Msg  string      `json:"msg"`
	Data interface{} `json:"data"`
}

func BuildResponse(resp http.ResponseWriter, errno int, msg string, data interface{}) {
	response := Response{
		Err:  errno,
		Msg:  msg,
		Data: data,
	}

	respData, _ := json.Marshal(response)
	resp.Write(respData)
	return
}

//反序列化Job
func UnpackJob(value []byte) (ret *Job, err error) {
	job := &Job{}
	err = json.Unmarshal(value, job)
	if err != nil {
		return nil, err
	}
	ret = job
	return
}

//从etcd的key中提取任务名
func ExtractJobName(jobKey string) string {
	return strings.TrimPrefix(jobKey, JOB_SAVE_DIR)
}

//从etcd的key中提取任务名
func ExtractKillerName(killerKey string) string {
	return strings.TrimPrefix(killerKey, JOB_KILLER_DIR)
}

func BuildJobEvent(eventType int, job *Job) *JobEvent {
	return &JobEvent{
		EventType: eventType,
		Job:       job,
	}
}

//构造任务执行计划
func BuildJobSchedulePlan(job *Job) (*JobSchedulePlan, error) {
	//解析表达式
	expr, err := cronexpr.Parse(job.CronExpr)
	if err != nil {
		return nil, err
	}

	//生成调度计划
	return &JobSchedulePlan{
		Job:      job,
		Expr:     expr,
		NextTime: expr.Next(time.Now()),
	}, nil
}

func BuildJobExecuteInfo(jobPlan *JobSchedulePlan) *JobExecuteInfo {
	cancel, cancelFunc := context.WithCancel(context.Background())
	//生成调度计划
	return &JobExecuteInfo{
		Job:        jobPlan.Job,
		PlanTime:   jobPlan.NextTime,
		RealTime:   time.Now(),
		CancelCtx:  cancel,
		CancelFunc: cancelFunc,
	}
}

//提取worker的Ip
func ExtractWorkerIp(workerKey string) string {
	return strings.TrimPrefix(workerKey, REGISTER_WORKERS_DIR)
}
